package com.jackykeke.opengldemo.renderer.cube;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;

import com.jackykeke.opengldemo.R;
import com.jackykeke.opengldemo.utils.ResReadUtil;
import com.jackykeke.opengldemo.utils.ShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

//基于索引法绘制立方体
//
//
//
// 如果我们采用glDrawArrays的方式，需要给这个立方体指定很多的顶点，
// 而使用glDrawElements方法绘制的时候，我们只需要指定8个顶点即可，
// 因此当涉及到顶点共享的时候，应该尽可能的使用glDrawElements方法完成绘制。
public class IndicesCubeRenderer implements GLSurfaceView.Renderer {

    private  FloatBuffer vertexBuffer, colorBuffer;

    private ShortBuffer indicesBuffer;

    private int mProgram;

    private static final int VERTEX_POSITION_SIZE = 3;

    private static final int VERTEX_COLOR_SIZE = 4;

    //点的坐标
    final float vertexPositions[] = {
            //正面矩形
//            -1.0f, 1.0f, 0.0f,    //正面左上0
//            -1.0f, -1.0f, 0.0f,   //正面左下1
//            1.0f, -1.0f, 0.0f,    //正面右下2
//            1.0f, 1.0f, 0.0f,     //正面右上3
//
//            //背面矩形
//            -1.0f, 1.0f, 0.0f,    //反面左上4
//            -1.0f, -1.0f,0.0f,   //反面左下5
//            1.0f, -1.0f, 0.0f,    //反面右下6
//            1.0f, 1.0f, -0.0f,     //反面右上7


            //正面矩形
            0.25f, 0.25f, 0.0f,  //V0
            -0.75f, 0.25f, 0.0f, //V1
            -0.75f, -0.75f, 0.0f, //V2
            0.25f, -0.75f, 0.0f, //V3

            //背面矩形
            0.75f, -0.25f, 0.0f, //V4
            0.75f, 0.75f, 0.0f, //V5
            -0.25f, 0.75f, 0.0f, //V6
            -0.25f, -0.25f, 0.0f //V7
    };

    final short indices[] = {
//            6, 7, 4, 6, 4, 5, //后面
//            6, 3, 7, 6, 2, 3,    //右面
//            6, 5, 1, 6, 1, 2,    //下面
//            0, 3, 2, 0, 2, 1,    //正面
//            0, 1, 5, 0, 5, 4,    //左面
//            0, 7, 3, 0, 4, 7,    //上面

            //背面
            5, 6, 7, 5, 7, 4,
            //左侧
            6, 1, 2, 6, 2, 7,
            //底部
            4, 7, 2, 4, 2, 3,
            //顶面
            5, 6, 7, 5, 7, 4,
            //右侧
            5, 0, 3, 5, 3, 4,
            //正面
            0, 1, 2, 0, 2, 3
    };

    final float colors[] = {
            0f, 0f, 0f, 1f,
            0f, 0f, 1f, 1f,
            0f, 1f, 0f, 1f,
            0f, 1f, 1f, 1f,
            1f, 0f, 0f, 1f,
            1f, 0f, 1f, 1f,
            1f, 1f, 0f, 1f,
            1f, 1f, 1f, 1f,

//            0.3f, 0.4f, 0.5f, 1f,   //V0
//            0.3f, 0.4f, 0.5f, 1f,   //V1
//            0.3f, 0.4f, 0.5f, 1f,   //V2
//            0.3f, 0.4f, 0.5f, 1f,   //V3
//            0.6f, 0.5f, 0.4f, 1f,   //V4
//            0.6f, 0.5f, 0.4f, 1f,   //V5
//            0.6f, 0.5f, 0.4f, 1f,   //V6
//            0.6f, 0.5f, 0.4f, 1f    //V7

    };


    public IndicesCubeRenderer() {
        //分配顶点内存空间 每个浮点型4字节空间
        vertexBuffer = ByteBuffer.allocateDirect(vertexPositions.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //传入指定的坐标数据
        vertexBuffer.put(vertexPositions);
        //从缓冲区的...位置开始
        vertexBuffer.position(0);


        //分配颜色内存空间 每个浮点型4字节空间
        colorBuffer = ByteBuffer.allocateDirect(colors.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        //传入颜色指定的数据
        colorBuffer.put(colors);
        colorBuffer.position(0);

        //分配索引内存空间,每个浮点型占4字节空间
        indicesBuffer = ByteBuffer.allocateDirect(indices.length * 4)
                .order(ByteOrder.nativeOrder())
                .asShortBuffer();
        //传入索引指定的数据
        indicesBuffer.put(indices);
        indicesBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);

        //编译
        final int vertexShaderId = ShaderUtil.compileVertexShader(ResReadUtil.readResource(R.raw.vertex_colorcube_shader));
        final int fragmentShaderId = ShaderUtil.compileFragmentShader(ResReadUtil.readResource(R.raw.fragment_colorcube_shader));

        mProgram = ShaderUtil.linkProgram(vertexShaderId, fragmentShaderId);
        GLES30.glUseProgram(mProgram);

//         public static void glVertexAttribPointer(
//        int indx, 句柄
//        int size,
//        int type,
//        boolean normalized,
//        int stride,
//        java.nio.Buffer ptr
//    )
        GLES30.glVertexAttribPointer(0, VERTEX_POSITION_SIZE, GLES30.GL_FLOAT, false, 0, vertexBuffer);
        //启用位置顶点属性
        GLES30.glEnableVertexAttribArray(0);


        GLES30.glVertexAttribPointer(1, VERTEX_COLOR_SIZE, GLES30.GL_FLOAT, false, 0, colorBuffer);
        //启用颜色顶点属性
        GLES30.glEnableVertexAttribArray(1);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

        GLES30.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indicesBuffer);
    }
}
